<template>
  <div class="person">
    <h2>情况一：监视ref定义的基本类型数据</h2>
    <h3>当前求和为：{{ sum }}</h3>
    <button @click="changeSum">点我sum+1</button>
    <h2>情况二：监视ref定义的对象类型数据</h2>
    <h3>当前颜色为：{{ light.color }}</h3>
    <h3>当前速度为：{{ light.speed.speed1 }}</h3>
    <button @click="changeLight">点我变颜色不触发</button>
    <button @click="changeSpeed">点我变速度1</button>
    <button @click="changeAll">点我都变</button>
    <h2>情况三：监视ref定义的对象类型数据，开启深度监视</h2>
    <h3>当前速度为：{{ light2.speed.speed2 }}</h3>
    <button @click="changeSpeed2">点我变速度2</button>
    <h2>情况四：监视reactive定义的对象类型数据</h2>
    <h3>当前颜色为：{{ light3.color }}</h3>
    <h3>当前速度为：{{ light3.speed.speed1 }}</h3>
    <button @click="changeLight3">点我变颜色</button>
    <button @click="changeSpeed3">点我变速度1</button>
    <button @click="changeAll3">点我都变</button>
    <h2>情况五：监视对象的一个属性</h2>
    <h3>英雄的血量为{{ hero.hp }}</h3>
    <h3>英雄的武器为{{ hero.items.weapon1 + hero.items.weapon2 }}</h3>
    <button @click="harm">-</button>
    <button @click="changeWeapon">changeWeapon</button>
    <h2>情况五最佳实践：监视对象的一个属性</h2>
    <h3>英雄的武器为{{ hero2.items.weapon1 + hero2.items.weapon2 }}</h3>
    <button @click="changeWeapon2">changeWeapon2</button>
    <h2>情况六：数组监听多个对象</h2>
    <h3>对象1{{ light3.speed }},对象2{{ hero.items.weapon1 }}</h3>
    <button @click="changeTwoObj">改变2个对象</button>
  </div>
</template>

<script setup lang="ts" name="PersonComponent">
import { ref, reactive, watch } from 'vue';
let sum = ref(0);

const changeSum = () => {
  sum.value++;
};
const stopWatch = watch(sum, (newValue, oldValue) => {
  console.log(newValue, oldValue);
  if (newValue > 10) {
    stopWatch();
  }
});

let light = ref({
  color: 'red',
  power: 100,
  speed: {
    speed1: 10,
    speed2: 20,
  },
});

watch(light, (newValue, oldValue) => {
  console.log('触发watch');
  console.log(newValue, oldValue);
});
const changeLight = () => {
  light.value.color = ['blue', 'red', 'green', 'yellow', 'black', 'pink'][
    Math.floor(Math.random() * 6)
  ];
};

const changeSpeed = () => {
  // 这样不触发watch
  light.value.speed = {
    speed1: Math.floor(Math.random() * 100),
    speed2: Math.floor(Math.random() * 100),
  };
};
const changeAll = () => {
  // 这样会触发watch
  // light.value = {
  //   color: '赛博',
  //   power: 100,
  //   speed: {
  //     speed1: 10,
  //     speed2: 20,
  //   },
  // };
  // 下面这种不会触发watch,也不会触发响应式
  light = ref({
    color: '赛博',
    power: 100,
    speed: {
      speed1: 999,
      speed2: 20,
    },
  });
};
let light2 = ref({
  speed: {
    speed1: 10,
    speed2: 20,
  },
});

watch(
  light2,
  (newValue, oldValue) => {
    console.log('触发deep');
    console.log(newValue, oldValue);
  },
  {
    deep: true,
  }
);
const changeSpeed2 = () => {
  light2.value.speed = {
    speed1: Math.floor(Math.random() * 100),
    speed2: Math.floor(Math.random() * 100),
  };
};
let light3 = reactive({
  color: 'red',
  power: 100,
  speed: {
    speed1: 10,
    speed2: 20,
  },
});
const changeLight3 = () => {
  light3.color += '~';
};
const changeSpeed3 = () => {
  light3.speed = {
    speed1: Math.floor(Math.random() * 100),
    speed2: Math.floor(Math.random() * 100),
  };
};
const changeAll3 = () => {
  // 不会触发watch
  // light3 = {
  //   color: '赛博',
  //   power: 100,
  //   speed: {
  //     speed1: 10,
  //     speed2: 20,
  //   },
  // };
  light3 = Object.assign(light3, {
    color: '赛博',
  });
};
watch(light3, (newValue, oldValue) => {
  console.log('触发watch');
  console.log(newValue, oldValue);
});
let hero = reactive({
  hp: 100,
  items: {
    weapon1: 'AK47',
    weapon2: 'AK48',
  },
});
watch(
  () => hero.hp,
  (newValue, oldValue) => {
    console.log('触发watch');
    console.log(newValue, oldValue);
  }
);
// 对象属性整体监听
watch(
  hero.items,
  // () => hero.items,
  (newValue, oldValue) => {
    console.log('触发watch2');
    console.log(newValue, oldValue);
  }
);
const harm = () => {
  hero.hp--;
  // 无法触发watch2,当()=>hero.items时可被监听
  // hero.items = {
  //   weapon1: 'AK45',
  //   weapon2: 'AK41',
  // };
  // 可以触发watch2，但这种写法很挫
  Object.assign(hero.items, {
    weapon1: 'AK45',
  });
};
const changeWeapon = () => {
  // 细枝末节改变也能触发整体监听watch2
  // 当()=>hero.items监听时，可以修改值，但是无法触发watch2
  hero.items.weapon2 = '圣剑';
};
// 最佳实践
let hero2 = reactive({
  hp: 100,
  items: {
    weapon1: 'AK47',
    weapon2: 'AK48',
  },
});
watch(
  () => hero2.items,
  // hero2.items,
  () => {
    console.log('触发watch3');
  },
  { deep: true }
);
const changeWeapon2 = () => {
  // 当()=>hero.items监听时，可以修改值，但是无法触发watch2
  hero2.items.weapon2 = '圣剑';
};
watch(
  [() => light3.speed.speed2, () => hero.items.weapon1],
  () => {
    console.log('触发watch6');
  }
  // { deep: true }
);
const changeTwoObj = () => {
  // light3.speed = {
  //   speed1: 88,
  //   speed2: 22,
  // };
  light3.speed.speed2 = 887;
  // hero.items.weapon1 = '雌雄双股剑';
};
</script>

<style scoped>
.person {
  color: red;
}
ul li {
  font-size: 20px;
}
</style>
